/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.lang.reflect;

import java.lang.annotation.*;
import java.util.Map;
import java.util.Objects;
import sun.reflect.annotation.AnnotationParser;
import sun.reflect.annotation.AnnotationSupport;
import sun.reflect.annotation.TypeAnnotationParser;
import sun.reflect.annotation.TypeAnnotation;
import sun.reflect.generics.repository.ConstructorRepository;

/**
 * {@link Method} 和 {@link Constructor} 通用功能的共享超类。
 *
 * @since 1.8
 */
public abstract class Executable extends AccessibleObject
    implements Member, GenericDeclaration {
    /*
     * Only grant package-visibility to the constructor.
     */
    Executable() {}

    /**
     * 允许代码共享的访问器方法
     */
    abstract byte[] getAnnotationBytes();

    /**
     * 允许代码共享的访问器方法
     */
    abstract Executable getRoot();

    /**
     * Executable 是否具有泛型信息。
     */
    abstract boolean hasGenericInformation();

    abstract ConstructorRepository getGenericInfo();

    boolean equalParamTypes(Class<?>[] params1, Class<?>[] params2) {
        /* Avoid unnecessary cloning */
        if (params1.length == params2.length) {
            for (int i = 0; i < params1.length; i++) {
                if (params1[i] != params2[i])
                    return false;
            }
            return true;
        }
        return false;
    }

    Annotation[][] parseParameterAnnotations(byte[] parameterAnnotations) {
        return AnnotationParser.parseParameterAnnotations(
               parameterAnnotations,
               sun.misc.SharedSecrets.getJavaLangAccess().
               getConstantPool(getDeclaringClass()),
               getDeclaringClass());
    }

    void separateWithCommas(Class<?>[] types, StringBuilder sb) {
        for (int j = 0; j < types.length; j++) {
            sb.append(types[j].getTypeName());
            if (j < (types.length - 1))
                sb.append(",");
        }

    }

    void printModifiersIfNonzero(StringBuilder sb, int mask, boolean isDefault) {
        int mod = getModifiers() & mask;

        if (mod != 0 && !isDefault) {
            sb.append(Modifier.toString(mod)).append(' ');
        } else {
            int access_mod = mod & Modifier.ACCESS_MODIFIERS;
            if (access_mod != 0)
                sb.append(Modifier.toString(access_mod)).append(' ');
            if (isDefault)
                sb.append("default ");
            mod = (mod & ~Modifier.ACCESS_MODIFIERS);
            if (mod != 0)
                sb.append(Modifier.toString(mod)).append(' ');
        }
    }

    String sharedToString(int modifierMask,
                          boolean isDefault,
                          Class<?>[] parameterTypes,
                          Class<?>[] exceptionTypes) {
        try {
            StringBuilder sb = new StringBuilder();

            printModifiersIfNonzero(sb, modifierMask, isDefault);
            specificToStringHeader(sb);

            sb.append('(');
            separateWithCommas(parameterTypes, sb);
            sb.append(')');
            if (exceptionTypes.length > 0) {
                sb.append(" throws ");
                separateWithCommas(exceptionTypes, sb);
            }
            return sb.toString();
        } catch (Exception e) {
            return "<" + e + ">";
        }
    }

    /**
     * Generate toString header information specific to a method or
     * constructor.
     */
    abstract void specificToStringHeader(StringBuilder sb);

    String sharedToGenericString(int modifierMask, boolean isDefault) {
        try {
            StringBuilder sb = new StringBuilder();

            printModifiersIfNonzero(sb, modifierMask, isDefault);

            TypeVariable<?>[] typeparms = getTypeParameters();
            if (typeparms.length > 0) {
                boolean first = true;
                sb.append('<');
                for(TypeVariable<?> typeparm: typeparms) {
                    if (!first)
                        sb.append(',');
                    // Class objects can't occur here; no need to test
                    // and call Class.getName().
                    sb.append(typeparm.toString());
                    first = false;
                }
                sb.append("> ");
            }

            specificToGenericStringHeader(sb);

            sb.append('(');
            Type[] params = getGenericParameterTypes();
            for (int j = 0; j < params.length; j++) {
                String param = params[j].getTypeName();
                if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
                    param = param.replaceFirst("\\[\\]$", "...");
                sb.append(param);
                if (j < (params.length - 1))
                    sb.append(',');
            }
            sb.append(')');
            Type[] exceptions = getGenericExceptionTypes();
            if (exceptions.length > 0) {
                sb.append(" throws ");
                for (int k = 0; k < exceptions.length; k++) {
                    sb.append((exceptions[k] instanceof Class)?
                              ((Class)exceptions[k]).getName():
                              exceptions[k].toString());
                    if (k < (exceptions.length - 1))
                        sb.append(',');
                }
            }
            return sb.toString();
        } catch (Exception e) {
            return "<" + e + ">";
        }
    }

    /**
     * 生成特定于方法或构造器的 toGenericString 头信息。
     */
    abstract void specificToGenericStringHeader(StringBuilder sb);

    /**
     * 返回表示声明此对象所表示的可执行元素的类或接口的 {@code Class} 对象。
     */
    public abstract Class<?> getDeclaringClass();

    /**
     * 返回此对象所表示的可执行元素的名称。
     */
    public abstract String getName();

    /**
     * 返回此对象所表示的可执行元素的 Java 语言{@linkplain Modifier 修饰符}。
     */
    public abstract int getModifiers();

    /**
     * 返回 {@code TypeVariable} 对象数组，这些对象按声明顺序表示
     * 此 {@code GenericDeclaration} 对象所表示的泛型声明所声明的类型变量。
     * 如果底层泛型声明未声明类型变量，则返回长度为 0 的数组。
     *
     * @return 表示此泛型声明所声明的类型变量的 {@code TypeVariable} 对象数组
     * @throws GenericSignatureFormatError 如果此泛型声明的泛型签名
     *     不符合 <cite>Java&trade; 虚拟机规范</cite>中指定的格式
     */
    public abstract TypeVariable<?>[] getTypeParameters();

    /**
     * 返回 {@code Class} 对象数组，这些对象按声明顺序表示
     * 此对象所表示的可执行元素的形式参数类型。
     * 如果底层可执行元素不接受参数，则返回长度为 0 的数组。
     *
     * @return 此对象所表示的可执行元素的参数类型
     */
    public abstract Class<?>[] getParameterTypes();

    /**
     * 返回此对象所表示的可执行元素的形式参数数量
     * （无论是显式声明、隐式声明还是都不是）。
     *
     * @return 此对象所表示的可执行元素的形式参数数量
     */
    public int getParameterCount() {
        throw new AbstractMethodError();
    }

    /**
     * 返回 {@code Type} 对象数组，这些对象按声明顺序表示
     * 此对象所表示的可执行元素的形式参数类型。
     * 如果底层可执行元素不接受参数，则返回长度为 0 的数组。
     *
     * <p>如果形式参数类型是参数化类型，
     * 为其返回的 {@code Type} 对象必须准确反映
     * 源代码中使用的实际类型参数。
     *
     * <p>如果形式参数类型是类型变量或参数化类型，则创建它。
     * 否则，解析它。
     *
     * @return 表示底层可执行元素的形式参数类型的 {@code Type} 数组，
     *     按声明顺序排列
     * @throws GenericSignatureFormatError
     *     如果泛型方法签名不符合
     *     <cite>Java&trade; 虚拟机规范</cite>中指定的格式
     * @throws TypeNotPresentException 如果底层可执行元素的任何参数类型
     *     引用不存在的类型声明
     * @throws MalformedParameterizedTypeException 如果底层可执行元素的
     *     任何参数类型引用由于任何原因无法实例化的参数化类型
     */
    public Type[] getGenericParameterTypes() {
        if (hasGenericInformation())
            return getGenericInfo().getParameterTypes();
        else
            return getParameterTypes();
    }

    /**
     * Behaves like {@code getGenericParameterTypes}, but returns type
     * information for all parameters, including synthetic parameters.
     */
    Type[] getAllGenericParameterTypes() {
        final boolean genericInfo = hasGenericInformation();

        // Easy case: we don't have generic parameter information.  In
        // this case, we just return the result of
        // getParameterTypes().
        if (!genericInfo) {
            return getParameterTypes();
        } else {
            final boolean realParamData = hasRealParameterData();
            final Type[] genericParamTypes = getGenericParameterTypes();
            final Type[] nonGenericParamTypes = getParameterTypes();
            final Type[] out = new Type[nonGenericParamTypes.length];
            final Parameter[] params = getParameters();
            int fromidx = 0;
            // If we have real parameter data, then we use the
            // synthetic and mandate flags to our advantage.
            if (realParamData) {
                for (int i = 0; i < out.length; i++) {
                    final Parameter param = params[i];
                    if (param.isSynthetic() || param.isImplicit()) {
                        // If we hit a synthetic or mandated parameter,
                        // use the non generic parameter info.
                        out[i] = nonGenericParamTypes[i];
                    } else {
                        // Otherwise, use the generic parameter info.
                        out[i] = genericParamTypes[fromidx];
                        fromidx++;
                    }
                }
            } else {
                // Otherwise, use the non-generic parameter data.
                // Without method parameter reflection data, we have
                // no way to figure out which parameters are
                // synthetic/mandated, thus, no way to match up the
                // indexes.
                return genericParamTypes.length == nonGenericParamTypes.length ?
                    genericParamTypes : nonGenericParamTypes;
            }
            return out;
        }
    }

    /**
     * 返回 {@code Parameter} 对象数组，这些对象表示
     * 此对象所表示的底层可执行元素的所有参数。
     * 如果可执行元素没有参数，则返回长度为 0 的数组。
     *
     * <p>底层可执行元素的参数不一定具有唯一的名称，
     * 或者在 Java 编程语言中是合法标识符的名称（JLS 3.8）。
     *
     * @throws MalformedParametersException 如果类文件包含
     * 格式不正确的 MethodParameters 属性。
     * @return 表示此对象所表示的可执行元素的所有参数的
     * {@code Parameter} 对象数组。
     */
    public Parameter[] getParameters() {
        // TODO: This may eventually need to be guarded by security
        // mechanisms similar to those in Field, Method, etc.
        //
        // Need to copy the cached array to prevent users from messing
        // with it.  Since parameters are immutable, we can
        // shallow-copy.
        return privateGetParameters().clone();
    }

    private Parameter[] synthesizeAllParams() {
        final int realparams = getParameterCount();
        final Parameter[] out = new Parameter[realparams];
        for (int i = 0; i < realparams; i++)
            // TODO: is there a way to synthetically derive the
            // modifiers?  Probably not in the general case, since
            // we'd have no way of knowing about them, but there
            // may be specific cases.
            out[i] = new Parameter("arg" + i, 0, this, i);
        return out;
    }

    private void verifyParameters(final Parameter[] parameters) {
        final int mask = Modifier.FINAL | Modifier.SYNTHETIC | Modifier.MANDATED;

        if (getParameterTypes().length != parameters.length)
            throw new MalformedParametersException("Wrong number of parameters in MethodParameters attribute");

        for (Parameter parameter : parameters) {
            final String name = parameter.getRealName();
            final int mods = parameter.getModifiers();

            if (name != null) {
                if (name.isEmpty() || name.indexOf('.') != -1 ||
                    name.indexOf(';') != -1 || name.indexOf('[') != -1 ||
                    name.indexOf('/') != -1) {
                    throw new MalformedParametersException("Invalid parameter name \"" + name + "\"");
                }
            }

            if (mods != (mods & mask)) {
                throw new MalformedParametersException("Invalid parameter modifiers");
            }
        }
    }

    private Parameter[] privateGetParameters() {
        // Use tmp to avoid multiple writes to a volatile.
        Parameter[] tmp = parameters;

        if (tmp == null) {

            // Otherwise, go to the JVM to get them
            try {
                tmp = getParameters0();
            } catch(IllegalArgumentException e) {
                // Rethrow ClassFormatErrors
                throw new MalformedParametersException("Invalid constant pool index");
            }

            // If we get back nothing, then synthesize parameters
            if (tmp == null) {
                hasRealParameterData = false;
                tmp = synthesizeAllParams();
            } else {
                hasRealParameterData = true;
                verifyParameters(tmp);
            }

            parameters = tmp;
        }

        return tmp;
    }

    boolean hasRealParameterData() {
        // If this somehow gets called before parameters gets
        // initialized, force it into existence.
        if (parameters == null) {
            privateGetParameters();
        }
        return hasRealParameterData;
    }

    private transient volatile boolean hasRealParameterData;
    private transient volatile Parameter[] parameters;

    private native Parameter[] getParameters0();
    native byte[] getTypeAnnotationBytes0();

    // Needed by reflectaccess
    byte[] getTypeAnnotationBytes() {
        return getTypeAnnotationBytes0();
    }

    /**
     * 返回 {@code Class} 对象数组，这些对象表示
     * 此对象所表示的底层可执行元素声明抛出的异常类型。
     * 如果可执行元素在其 {@code throws} 子句中未声明异常，
     * 则返回长度为 0 的数组。
     *
     * @return 此对象所表示的可执行元素声明抛出的异常类型
     */
    public abstract Class<?>[] getExceptionTypes();

    /**
     * 返回 {@code Type} 对象数组，这些对象表示
     * 此可执行对象声明抛出的异常。
     * 如果底层可执行元素在其 {@code throws} 子句中未声明异常，
     * 则返回长度为 0 的数组。
     *
     * <p>如果异常类型是类型变量或参数化类型，则创建它。
     * 否则，解析它。
     *
     * @return 表示底层可执行元素抛出的异常类型的 Type 数组
     * @throws GenericSignatureFormatError
     *     如果泛型方法签名不符合
     *     <cite>Java&trade; 虚拟机规范</cite>中指定的格式
     * @throws TypeNotPresentException 如果底层可执行元素的
     *     {@code throws} 子句引用不存在的类型声明
     * @throws MalformedParameterizedTypeException 如果
     *     底层可执行元素的 {@code throws} 子句引用
     *     由于任何原因无法实例化的参数化类型
     */
    public Type[] getGenericExceptionTypes() {
        Type[] result;
        if (hasGenericInformation() &&
            ((result = getGenericInfo().getExceptionTypes()).length > 0))
            return result;
        else
            return getExceptionTypes();
    }

    /**
     * 返回描述此 {@code Executable} 的字符串，包括任何类型参数。
     * @return 描述此 {@code Executable} 的字符串，包括任何类型参数
     */
    public abstract String toGenericString();

    /**
     * 如果此可执行元素被声明为接受可变数量的参数，则返回 {@code true}；
     * 否则返回 {@code false}。
     *
     * @return 当且仅当此可执行元素被声明为接受可变数量的参数时返回 {@code true}。
     */
    public boolean isVarArgs()  {
        return (getModifiers() & Modifier.VARARGS) != 0;
    }

    /**
     * 如果此可执行元素是合成构造，则返回 {@code true}；
     * 否则返回 {@code false}。
     *
     * @return 当且仅当此可执行元素是
     * <cite>Java&trade; 语言规范</cite>定义的合成构造时返回 true。
     * @jls 13.1 The Form of a Binary
     */
    public boolean isSynthetic() {
        return Modifier.isSynthetic(getModifiers());
    }

    /**
     * 返回 {@code Annotation} 数组的数组，这些数组按声明顺序表示
     * 此对象所表示的 {@code Executable} 的形式参数上的注解。
     * 合成和强制参数（见下面的解释），如内部类构造器的外部 "this" 参数
     * 将在返回的数组中表示。如果可执行元素没有参数
     * （意味着没有形式参数、合成参数和强制参数），将返回长度为 0 的数组。
     * 如果 {@code Executable} 有一个或多个参数，
     * 对于没有注解的每个参数，返回长度为零的嵌套数组。
     * 返回数组中包含的注解对象是可序列化的。
     * 此方法的调用者可以自由修改返回的数组；
     * 这不会影响返回给其他调用者的数组。
     *
     * 编译器可能会向方法的参数列表添加在源代码中隐式声明的额外参数（"强制"），
     * 以及在源代码中既不隐式也不显式声明的参数（"合成"）。
     * 有关更多信息，请参见 {@link java.lang.reflect.Parameter}。
     *
     * @see java.lang.reflect.Parameter
     * @see java.lang.reflect.Parameter#getAnnotations
     * @return 表示此对象所表示的可执行元素的形式参数和隐式参数上的注解的
     *    数组的数组，按声明顺序排列
     */
    public abstract Annotation[][] getParameterAnnotations();

    Annotation[][] sharedGetParameterAnnotations(Class<?>[] parameterTypes,
                                                 byte[] parameterAnnotations) {
        int numParameters = parameterTypes.length;
        if (parameterAnnotations == null)
            return new Annotation[numParameters][0];

        Annotation[][] result = parseParameterAnnotations(parameterAnnotations);

        if (result.length != numParameters)
            handleParameterNumberMismatch(result.length, numParameters);
        return result;
    }

    abstract void handleParameterNumberMismatch(int resultLength, int numParameters);

    /**
     * {@inheritDoc}
     * @throws NullPointerException  {@inheritDoc}
     */
    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
        Objects.requireNonNull(annotationClass);
        return annotationClass.cast(declaredAnnotations().get(annotationClass));
    }

    /**
     * {@inheritDoc}
     * @throws NullPointerException {@inheritDoc}
     */
    @Override
    public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
        Objects.requireNonNull(annotationClass);

        return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass);
    }

    /**
     * {@inheritDoc}
     */
    public Annotation[] getDeclaredAnnotations()  {
        return AnnotationParser.toArray(declaredAnnotations());
    }

    private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;

    private synchronized  Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
        if (declaredAnnotations == null) {
            Executable root = getRoot();
            if (root != null) {
                declaredAnnotations = root.declaredAnnotations();
            } else {
                declaredAnnotations = AnnotationParser.parseAnnotations(
                    getAnnotationBytes(),
                    sun.misc.SharedSecrets.getJavaLangAccess().
                    getConstantPool(getDeclaringClass()),
                    getDeclaringClass());
            }
        }
        return declaredAnnotations;
    }

    /**
     * 返回一个 {@code AnnotatedType} 对象，该对象表示使用类型来指定
     * 此 Executable 所表示的方法/构造器的返回类型。
     *
     * 如果此 {@code Executable} 对象表示构造器，
     * {@code AnnotatedType} 对象表示构造对象的类型。
     *
     * 如果此 {@code Executable} 对象表示方法，
     * {@code AnnotatedType} 对象表示使用类型来指定方法的返回类型。
     *
     * @return 表示此 {@code Executable} 所表示的方法或构造器的返回类型的对象
     */
    public abstract AnnotatedType getAnnotatedReturnType();

    /* Helper for subclasses of Executable.
     *
     * Returns an AnnotatedType object that represents the use of a type to
     * specify the return type of the method/constructor represented by this
     * Executable.
     */
    AnnotatedType getAnnotatedReturnType0(Type returnType) {
        return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),
                sun.misc.SharedSecrets.getJavaLangAccess().
                        getConstantPool(getDeclaringClass()),
                this,
                getDeclaringClass(),
                returnType,
                TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN);
    }

    /**
     * 返回一个 {@code AnnotatedType} 对象，该对象表示使用类型来指定
     * 此 Executable 对象所表示的方法/构造器的接收者类型。
     * 方法/构造器的接收者类型仅在方法/构造器具有<em>接收者参数</em>时可用（JLS 8.4.1）。
     *
     * 如果此 {@code Executable} 对象表示没有接收者参数的构造器或实例方法，
     * 或者具有在其类型上没有注解的接收者参数，
     * 则返回值是表示没有注解的元素的 {@code AnnotatedType} 对象。
     *
     * 如果此 {@code Executable} 对象表示静态方法，则返回值为 null。
     *
     * @return 表示此 {@code Executable} 所表示的方法或构造器的接收者类型的对象
     */
    public AnnotatedType getAnnotatedReceiverType() {
        if (Modifier.isStatic(this.getModifiers()))
            return null;
        return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),
                sun.misc.SharedSecrets.getJavaLangAccess().
                        getConstantPool(getDeclaringClass()),
                this,
                getDeclaringClass(),
                getDeclaringClass(),
                TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER);
    }

    /**
     * 返回 {@code AnnotatedType} 对象数组，这些对象表示使用类型来指定
     * 此 Executable 所表示的方法/构造器的形式参数类型。
     * 数组中对象的顺序对应于方法/构造器声明中形式参数类型的顺序。
     *
     * 如果方法/构造器未声明参数，则返回长度为 0 的数组。
     *
     * @return 表示此 {@code Executable} 所表示的方法或构造器的
     * 形式参数类型的对象数组
     */
    public AnnotatedType[] getAnnotatedParameterTypes() {
        return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes0(),
                sun.misc.SharedSecrets.getJavaLangAccess().
                        getConstantPool(getDeclaringClass()),
                this,
                getDeclaringClass(),
                getAllGenericParameterTypes(),
                TypeAnnotation.TypeAnnotationTarget.METHOD_FORMAL_PARAMETER);
    }

    /**
     * 返回 {@code AnnotatedType} 对象数组，这些对象表示使用类型来指定
     * 此 Executable 所表示的方法/构造器的声明异常。
     * 数组中对象的顺序对应于方法/构造器声明中异常类型的顺序。
     *
     * 如果方法/构造器未声明异常，则返回长度为 0 的数组。
     *
     * @return 表示此 {@code Executable} 所表示的方法或构造器的
     * 声明异常的对象数组
     */
    public AnnotatedType[] getAnnotatedExceptionTypes() {
        return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes0(),
                sun.misc.SharedSecrets.getJavaLangAccess().
                        getConstantPool(getDeclaringClass()),
                this,
                getDeclaringClass(),
                getGenericExceptionTypes(),
                TypeAnnotation.TypeAnnotationTarget.THROWS);
    }

}
